#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <string>
#include <sys/types.h>

std::string PrintToHex(const pthread_t &tid)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer),"0x%lx",tid);
    return buffer;
}

// void* Threadrun(void* args)
// {
//     int cnt = 5;
//     while(cnt--)
//     {
//         std::cout<< *(static_cast<std::string*>(args)) <<" running, tid: "<<std::endl;
//         sleep(1);
//     }
//     return nullptr;
// }

class ThreadData
{
public:
    ThreadData(std::string name, int x, int y)
        :_name(name), _x(x), _y(y)
    { }

    int Excute()
    {
        return _x + _y;
    }
    int _x;
    int _y;
    std::string _name;
};

class ThreadResult
{
public:
    std::string print()
    {
        return std::to_string(_x) + '+' + std::to_string(_y) + '=' + std::to_string(_result);
    }
    ThreadResult(int x, int y, int ret)
        :_x(x), _y(y), _result(ret)
    { }
private:
    int _x;
    int _y;
    int _result;
};

// void* Threadrun(void* args)
// {
//     ThreadData* td = static_cast<ThreadData*>(args);
//     std::cout<<td->_name<<" running!"<<std::endl;
//     ThreadResult* ret = new ThreadResult(td->_x,td->_y,td->Excute());
//     delete td;

//     return (void*)ret;
// }

void* Threadrun(void* args)
{
    std::string* s = static_cast<std::string*>(args);
    std::string* ret = new std::string(*s);
    int cnt = 5;
    while(cnt)
    {
        std::cout<<*ret<<" is running"<<std::endl;
        cnt--;
        sleep(1);
    }
    delete s;
    return ret;
}

int main()
{
    std::vector<pthread_t> v;
    int N = 5;
    for(int i=0;i<N;i++)
    {
        pthread_t tid;
        std::string* name = new std::string("thread - " + std::to_string(i));
        int n = pthread_create(&tid, nullptr, Threadrun, name);
        std::string id = PrintToHex(tid);
        if(n == 0)
        {
            std::cout<<id<<" -> "<<*name<<" : success loading!"<<std::endl;
            v.push_back(tid);
        }
        else
        {
            std::cout<<id<<" -> "<<*name<<" : fail loading!"<<std::endl;
        }
    }

    sleep(3);

    std::cout<<"Main cancel every thread"<<std::endl;
    for(auto& x : v)
    {
        pthread_cancel(x);
    }

    std::cout<<"Main Join"<<std::endl;
    sleep(1);

    for(auto& x : v)
    {
        void* ret = nullptr;
        //int y=0;
        int y = pthread_join(x, (void**)&ret);
        //if(y == 0)
        //{
        //    std::cout<<PrintToHex(x)<<" -> quit!   ret: "<<*static_cast<std::string*>(ret)<<std::endl;
        //}
        //else
        //{
            std::cout<<PrintToHex(x) << "->  The thread is unthreaded , y: "<< y <<"  ret: "<<(long long int)(ret)<<std::endl;
        //}
    }

    return 0;
}



// int main()
// {
//     pthread_t tid;
//     std::string name = "thread-1";
//     ThreadData* td = new ThreadData(name, 1243566, 12235);
//     int c = pthread_create(&tid, nullptr, Threadrun, (void*)td);
//     std::cout<<"Main create ->  " <<PrintToHex(tid)<<std::endl;
//     void* result = nullptr;

//     int n = pthread_join(tid, (void**)&result);
//     std::cout<<(static_cast<ThreadResult*>(result))->print()<<std::endl;

//     if(n == 0)
//         std::cout<<"wait success"<<std::endl;
//     else
//         std::cout<<"No wait success"<<std::endl;
//     return 0;
// }